import axios from "axios";
import type { AxiosError, AxiosInstance, AxiosResponse, InternalAxiosRequestConfig } from 'axios'
import { BASE_URL, SIG } from "@/utils/env";
import { message } from 'antd'
import type { EnhancedStore } from "@reduxjs/toolkit";
import type { RootState } from "@/store";
import { isFileOrBlob, sortParams } from "@/utils/tool";
import md5 from "md5";

export const instance: AxiosInstance = axios.create({
  baseURL: BASE_URL,
  headers: {
    "Content-Type": "multipart/form-data"
  },
});

// 请求拦截
instance.interceptors.request.use(
  async (config: InternalAxiosRequestConfig): Promise<InternalAxiosRequestConfig> => {
    const store: EnhancedStore = await import('@/store').then(module => module.default)
    const state: RootState = store.getState()
    config.headers.Authorization = `${state?.app?.userInfo?.user_token}`
    return config;
  },
  (error: AxiosError): Promise<AxiosError> => {
    return Promise.reject(error);
  }
);

// 响应拦截
instance.interceptors.response.use(
  (response: AxiosResponse): Promise<AxiosResponse> => {
    const { data } = response
    if (data?.code == 0) {
      return Promise.resolve(response.data)
    } else {
      if ([997].includes(data?.code)) {
        message.error('Token无效了，请重新登录')
      } else {
        message.error(`${data?.msg || ''}-${data?.error || ''}-${data?.data?.msg}-【code:${data?.code}】`)
      }
      return Promise.reject(data)
    }
  },
  (error: AxiosError): Promise<AxiosError> => {
    message.error(error.message)
    return Promise.reject(error);
  }
);

type NewParams = {
  [key: string]: any
} | FormData
type Method = 'get' | 'post' | 'put' | 'delete' | 'patch'
export default async function request(url: string, params: Object | FormData, method: Method): Promise<AxiosResponse> {
  const store: EnhancedStore = await import('@/store').then(module => module.default)
  const state: RootState = store.getState()
  const newParams: NewParams = params
  const sigParams: {[key:string]:any} = {}
  
  if (newParams instanceof FormData) {
    newParams.append(
      "admin_user_id", String(state?.app?.userInfo?.admin_user_id)
    );
    for(const [key, value] of newParams.entries()){
      if(!isFileOrBlob(value)){
        const replaceVal = (value as string).replace(/\r\n/g, '\n')
        sigParams[key] = replaceVal
        newParams.set(key, replaceVal)
      }
    }
    newParams.append('sig', md5(sortParams(sigParams)+SIG))
  } else {
    newParams.admin_user_id = newParams.admin_user_id || state?.app?.userInfo?.admin_user_id;
    for(const key in newParams){
      sigParams[key] = newParams[key]
      if(typeof newParams[key] === 'string'){
        const replaceVal = newParams[key].replace(/\r\n/g, '\n')
        sigParams[key] = replaceVal
        newParams[key] = replaceVal
      }
    }
    newParams.sig = md5(sortParams(sigParams)+SIG)
  }
  return instance.request({
    url,
    method,
    data: ["put", "post", "delete", "patch"].includes(method.toLocaleLowerCase()) ? newParams : undefined,
    params: !["put", "post", "delete", "patch"].includes(method.toLocaleLowerCase()) ? newParams : undefined,
  });
}
